Release 10.1A: OpenEdge Development:
Web Services


StockQuotes sample walk-through

StockQuotes.p follows these steps to prepare, call, and process the output from a quote request (source code edited and formatted for clarity):

  1. Prompts for the stock symbol(s) to populate the XML document entered using the Enter Stock Symbols prompt:
  2. DEFINE VARIABLE fillin-1 AS CHARACTER FORMAT "x(40)". 
    DEFINE VARIABLE text-1 AS CHARACTER FORMAT "x(50)" VIEW-AS TEXT. 
    DEFINE VARIABLE fillin-2 AS CHARACTER  
        VIEW-AS EDITOR LARGE SIZE 63 BY 15 SCROLLBAR-VERTICAL LABEL "". 
    DEFINE VARIABLE text-2 AS CHARACTER FORMAT "x(80)" VIEW-AS TEXT. 
    DEFINE BUTTON bgetQuote LABEL "getQuote" SIZE 14 BY 1. 
    DEFINE FRAME fTemp 
        text-1 AT ROW 1.5 COLUMN 2 
        fillin-1 AT ROW 1.25 COLUMN 25 
        text-2 AT ROW 3 COLUMN 2 
        bgetQuote AT ROW 4.5 COLUMN 30 
        fillin-2 AT ROW 6 COLUMN 5  
        WITH NO-LABELS SIZE 82 BY 22 THREE-D. 
    . 
    . 
    . 
    FILLIN-1:SCREEN-VALUE = "PRGS". 
    text-1:SCREEN-VALUE = "Enter Stock Symbols". 
    text-2:SCREEN-VALUE = "To get multiple quotes enter Ticker symbols 
    seperated by , (eg. PRGS,GE)". 
    ENABLE ALL WITH FRAME fTemp. 
    

  3. Creates a Web service object in the 4GL:
  4. DEFINE VARIABLE hWS AS HANDLE. 
    . 
    . 
    . 
    CREATE SERVER hWS. 
    

  5. Connects to the Web service (which has only one valid service and port):
  6. hWS:CONNECT("-WSDL 
                  http://www.swanandmokashi.com/HomePage/WebServices/StockQ
    uotes.asmx?wsdl).   
    IF NOT hWS:CONNECTED() THEN 
        MESSAGE "SERVER NOT CONNECTED" VIEW-AS ALERT-BOX. 
    

  7. Sets the handle to the port type in the WSDL where the Web service operation is defined and waits for the user to invoke the request:
  8. DEFINE VARIABLE hPortType AS HANDLE. 
    . 
    . 
    . 
    RUN StockQuotesSoap SET hPortType ON SERVER hWS. 
    IF NOT VALID-HANDLE(hPortType) THEN 
        MESSAGE "hPortType invalid: " VALID-HANDLE(hPortType)  
            VIEW-AS ALERT-BOX. 
    WAIT-FOR CLOSE OF CURRENT-WINDOW. 
    

  9. When the user clicks the getQuote button, StockQuotes.p:
    1. Constructs the XML document that is input to the Web service operation. The document is created in this form:
    2. <s0:GetStockQuotes xmlns:s0="http://swanandmokashi.com/"> 
              <s0:QuoteTicker>stock-symbol(s)</s0:QuoteTicker> 
      </s0:GetStockQuotes>  
      

      This is the code, which also saves the document as a LONGCHAR:

      DEFINE VARIABLE lcSymbol AS LONGCHAR  
          VIEW-AS EDITOR LARGE SIZE 60 BY 20. 
      DEFINE VARIABLE lcQuote AS LONGCHAR  
          VIEW-AS EDITOR LARGE SIZE 60 BY 20. 
      DEFINE VARIABLE hDoc AS HANDLE. 
      DEFINE VARIABLE hRoot AS HANDLE. 
      DEFINE VARIABLE hChild AS HANDLE. 
      DEFINE VARIABLE hNextChild AS HANDLE. 
      DEFINE VARIABLE hNextNode AS HANDLE. 
      DEFINE VARIABLE hTextNode AS HANDLE. 
      . 
      . 
      . 
      ON CHOOSE of bgetQuote 
      DO: 
        . 
        . 
        . 
        CREATE X-DOCUMENT hDoc. 
        CREATE X-NODEREF hRoot. 
        CREATE X-NODEREF hChild. 
        CREATE X-NODEREF hNextChild. 
        CREATE X-NODEREF hNextNode.  
        CREATE x-noderef hTextNode. 
        hDoc:CREATE-NODE-NAMESPACE(hRoot, "http://swanandmokashi.com/", 
                                   "s0:GetStockQuotes", "element").  
        hRoot:SET-ATTRIBUTE("xmlns:s0", "http://swanandmokashi.com/"). 
        hDoc:APPEND-CHILD(hRoot). 
        hDoc:CREATE-NODE-NAMESPACE(hChild, "http://swanandmokashi.com/", 
                                   "s0:QuoteTicker", "element").  
        hRoot:APPEND-CHILD(hChild). 
        hDoc:CREATE-NODE(hTextNode, ?, "text"). 
        hTextNode:NODE-VALUE = FILLIN-1:SCREEN-VALUE. 
        hChild:APPEND-CHILD(hTextNode). 
        hDoc:SAVE("longchar", lcSymbol). 
        . 
        . 
        . 
      

    3. Invokes the GetStockQuotes operation in the Web service by making a procedure call:
    4. DEFINE VARIABLE lcQuote AS LONGCHAR  
          VIEW-AS EDITOR LARGE SIZE 60 BY 20. 
      . 
      . 
      . 
      ON CHOOSE of bgetQuote 
      DO: 
        . 
        . 
        . 
        RUN GetStockQuotes IN hPortType (INPUT lcSymbol, OUTPUT lcQuote) 
            NO-ERROR. 
      

    5. Checks for errors and manages the information for any that occur (see the "Common procedure for SOAP fault handling" section):
    6. DEFINE VARIABLE err AS LOGICAL. 
      . 
      . 
      . 
      ON CHOOSE of bgetQuote 
      DO: 
        . 
        . 
        . 
        RUN GetStockQuotes IN hPortType (INPUT lcSymbol, OUTPUT lcQuote) 
            NO-ERROR. 
        RUN ErrorInfo (OUTPUT err). 
       . 
       . 
       . 
      

    7. If there are no errors, loads the XML document that was passed back as a LONGCHAR OUTPUT parameter:
    8. ON CHOOSE of bgetQuote 
      DO: 
        . 
        . 
        . 
        IF NOT err THEN 
        DO: 
           hDoc:LOAD("longchar", lcQuote, FALSE). 
           . 
           . 
           . 
      

    9. The Web service returns the output XML document with the following structure (shown for a single quote example, PRGS):
    10. <GetStockQuotesResponse xmlns="http://swanandmokashi.com/" 
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
          xmlns:xml="http://www.w3.org/XML/1998/namespace"  
          xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
          <GetStockQuotesResult> 
              <Quote> 
                  <CompanyName>PROGRESS SOFT</CompanyName> 
                  <StockTicker>PRGS</StockTicker> 
                  <StockQuote>21.41</StockQuote> 
                  <LastUpdated>4:00pm</LastUpdated> 
                  <Change>+0.86</Change> 
                  <OpenPrice>N/A</OpenPrice> 
                  <DayHighPrice>21.60</DayHighPrice> 
                  <DayLowPrice>20.41</DayLowPrice> 
                  <Volume>160721</Volume> 
                  <MarketCap>740.4M</MarketCap> 
                  <YearRange>11.50 - 24.06</YearRange> 
              </Quote> 
          </GetStockQuotesResult> 
      </GetStockQuotesResponse> 
      

      The client then parses this document to get the relevant information and put it into a CHARACTER variable for display:

      DEFINE VARIABLE cResult AS CHARACTER INITIAL "". . . . 
      ON CHOOSE of bgetQuote 
      DO: 
        . 
        . 
        . 
        IF NOT err THEN 
        DO: 
          hDoc:LOAD("longchar", lcQuote, FALSE). 
          hDoc:GET-DOCUMENT-ELEMENT(hRoot).  
            /* hRoot = GetStockQuotesResponse */ 
          IF hRoot:SUBTYPE = "ELEMENT" AND  
             hRoot:NAME = "GetStockQuotesResponse" THEN 
          DO: 
            hRoot:GET-CHILD(hChild, 1). 
              /* hChild = GetStockQuotesResult */  
            IF hChild:SUBTYPE = "ELEMENT" AND  
               hChild:NAME = "GetStockQuotesResult" THEN 
            DO i = 1 TO hChild:NUM-CHILDREN: 
              hChild:GET-CHILD(hNextChild, i). 
                /* hNextChild = Quote */ 
              IF hNextChild:SUBTYPE = "ELEMENT" AND  
                 hNextChild:NAME = "Quote" THEN 
              DO j = 1 TO hNextChild:NUM-CHILDREN:  
                hNextChild:GET-CHILD(hNextNode, j). 
                IF hNextNode:NAME = "CompanyName" THEN 
                DO: 
                  hNextNode:GET-CHILD(hTextNode, 1). 
                  IF hTextNode:SUBTYPE = "TEXT" THEN  
                    cResult = cResult + hNextNode:NAME + " = " + 
                              hTextNode:NODE-VALUE + "~n". 
                END. 
                . 
                . 
                . 
                IF hNextNode:NAME = "YearRange" THEN 
                DO: 
                  hNextNode:GET-CHILD(hTextNode, 1). 
                  IF hTextNode:SUBTYPE = "TEXT" THEN  
                    cResult = cResult + hNextNode:NAME + " = " + 
                              hTextNode:NODE-VALUE + "~n".  
                END. 
              END. /* hNextChild = Quote */ 
            END. /* hChild = GetStockQuotesResult*/  
          END. /*  hRoot = GetStockQuotesResponse */ 
        END. /* IF NOT err */ 
      . . . 
      END. /* bgetQuote */ 
      

    11. Displays the CHARACTER variable containing the data in an EDITOR widget:
    12. ON CHOOSE of bgetQuote 
      DO: 
        . 
        . 
        . 
        fillin-2:SCREEN-VALUE = cResult. 
      END. /* bgetQuote */ 
      

  10. Cleans up by running this code:
  11. DELETE PROCEDURE hPortType. 
    hWS:DISCONNECT().  
    DELETE OBJECT hWS. 
    

    Which:

    1. Deletes the procedure object.
    2. Disconnects from the Web service.
    3. Deletes the Web service object.

Copyright © 2005 Progress Software Corporation
www.progress.com
Voice: (781) 280-4000
Fax: (781) 280-4095